<?php

declare(strict_types=1);
/**
 * This file is part of habo_new_media.
 *
 * @link     https://www.berlen.cn/
 * @contact  tech@berlen.cn
 * @license  http://gitlab.rehou.cn/habo/habo_new_media/-/blob/master/README.md
 */
namespace app\service\batch\kuaishou;

use app\enum\CommonEnum;
use app\enum\ConfigEnum;
use app\enum\KsBidEnum;
use app\enum\KuaiShouEnum;
use app\model\KsBidTaskContentModel;
use app\model\KsBidTaskLogModel;
use app\model\KsBidTaskModel;
use app\service\batch\MediaInterface;
use app\service\batch\MediaService;
use app\service\client\AccountService;
use app\service\kuaishou\AdvertiserService;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;

class UnitBidPushService extends MediaService implements MediaInterface
{
    use UnitBidTrait;
    /**
     * @var string 批量改价锁
     */
    protected const BATCH_KEY = ConfigEnum::CACHE_CONFIG[KuaiShouEnum::BATCH_CONFIG_LOCK_KEY]['unit_bid_push'];

    /**
     * @var null|KsBidTaskModel 任务模型
     */
    private ?KsBidTaskModel $taskModel;

    /**
     * @var null|KsBidTaskContentModel 任务内容模型
     */
    private ?KsBidTaskContentModel $contentModel;

    /**
     * @var null|KsBidTaskLogModel 任务日志模型
     */
    private ?KsBidTaskLogModel $logModel;

    /**
     * 修改出价.
     *
     * @param KsBidTaskContentModel $model 出价内容模型
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function unitBidPush(KsBidTaskContentModel $model): bool
    {
        $this->contentModel = $model;
        if (! $this->contentModel->getKey()) {
            return self::setError('未知出价记录失败');
        }

        $this->taskModel = (new KsBidTaskModel())
            ->where('id', $this->contentModel->getAttr('task_id'))
            ->find();
        if (! $this->taskModel instanceof KsBidTaskModel || ! $this->taskModel->getKey()) {
            return self::setError('获取出价失败');
        }

        $this->logModel = (new KsBidTaskLogModel())
            ->where('content_id', $this->contentModel->getKey())
            ->find();
        if (! $this->logModel instanceof KsBidTaskLogModel || ! $this->logModel->getKey()) {
            return self::setError('获取出价记录失败');
        }
        $bid = [];
        // 修改出价
        if ($this->contentModel->getAttr('type') != KsBidEnum::TASK_TYPE_FUR) {
            $bid['deep_conversion_bid'] = $this->contentModel->getAttr('deep_conversion_bid') * 1000;
        }
        $bid['cpa_bid'] = $this->contentModel->getAttr('cpa_bid') * 1000;
        $bid['unit_id'] = $this->contentModel->getAttr('ks_unit_id');
        $bid['unit_name'] = $this->contentModel->getAttr('ks_unit_name');
        $bid['advertiser_id'] = $this->taskModel->getAttr('advertiser_id');

        // 修改出价
        $res = $this->updateUnitBid($bid);
        if ($res === false) {
            if (! $this->setBidFail()) {
                return false;
            }
        } else {
            if (! $this->setBidSuccess($res)) {
                return false;
            }
        }
        // 更新任务状态
        return $this->unitBidFinish();
    }

    /**
     *  更新组出价.
     *
     * @param array $params 组信息
     * @return bool|mixed|string
     */
    private function updateUnitBid(array $params = [])
    {
        if (! $this->contentModel instanceof KsBidTaskContentModel || ! $this->contentModel->getKey()) {
            return self::setError('未知组信息');
        }
        $token = AccountService::getToken(CommonEnum::KS_MEDIA, $this->taskModel->getAttr('advertiser_id'));
        if (! $token) {
            return self::setError('token获取失败');
        }
        $headers = [
            'Access-Token' => $token,
            'Content-Type' => 'application/json',
            'K-RealUser-IP' => $this->taskModel->getAttr('ip_address'),
        ];

        return AdvertiserService::updateUnit($headers, $params);
    }

    /**
     *  出价修改成功.
     *
     * @param mixed $res
     */
    private function setBidSuccess($res = []): bool
    {
        if (! $this->contentModel instanceof KsBidTaskContentModel || ! $this->contentModel->getKey()) {
            return self::setError('未知组信息');
        }
        if (! $this->logModel instanceof KsBidTaskLogModel || ! $this->logModel->getKey()) {
            return self::setError('未知组日志信息');
        }

        $this->contentModel->setAttrs([
            'status' => KsBidTaskContentModel::STATUS_SUCCESS,
        ]);
        if (! $this->contentModel->save()) {
            return self::setError('保存组出价成功结果信息失败');
        }

        $this->logModel->setAttrs([
            'status' => KsBidTaskLogModel::STATUS_SUCCESS,
            'error_json' => json_encode($res),
        ]);
        if (! $this->logModel->save()) {
            return self::setError('保存组出价成功结果日志失败');
        }
        return true;
    }

    /**
     *  出价修改失败.
     */
    private function setBidFail(): bool
    {
        if (! $this->contentModel instanceof KsBidTaskContentModel || ! $this->contentModel->getKey()) {
            return self::setError('未知组信息');
        }
        if (! $this->logModel instanceof KsBidTaskLogModel || ! $this->logModel->getKey()) {
            return self::setError('未知组日志信息');
        }

        $this->contentModel->setAttrs([
            'status' => KsBidTaskContentModel::STATUS_FAIL,
        ]);
        if (! $this->contentModel->save()) {
            return self::setError('保存组出价错误结果信息失败');
        }

        $this->logModel->setAttrs([
            'status' => KsBidTaskLogModel::STATUS_FAIL,
            'error_json' => json_encode([AdvertiserService::getError(0)]),
            'error_msg' => AdvertiserService::getError(0),
        ]);
        if (! $this->logModel->save()) {
            return self::setError('保存组出价错误结果日志失败');
        }
        return true;
    }
}
